package com.anlogic.sdk.app.handlers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.Logger;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import com.anlogic.sdk.app.model.ApplicationProject;
import com.anlogic.sdk.app.model.IApplicationProject;
import com.anlogic.sdk.app.ui.ChangeReferenceBspDialog;
import com.anlogic.sdk.bsp.model.IPlatformProject;
import com.anlogic.sdk.utils.LogUtils;
import com.anlogic.sdk.utils.ProjectUtils;
import com.anlogic.sdk.utils.UIUtils;

public class ChangeReferenceBspHandler extends AbstractHandler {
	private static Logger logger = LogUtils.getLogger(ChangeReferenceBspHandler.class);
	
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		IProject project = ProjectUtils.getSelectedProject();
		if (project == null) {
			UIUtils.showMessageDialog("Change Referenced BSP", "Project can not be null!", MessageDialog.ERROR);
			return null;
		}
		if (!ProjectUtils.isApplicationProject(project)) {
			UIUtils.showMessageDialog("Change Referenced BSP", "Project must be Application Project!", MessageDialog.ERROR);
			return null;
		}
		
		IApplicationProject appProj = new ApplicationProject(project);
		appProj.restoreMetaData();
		
		IPlatformProject bspProj = appProj.getBspProj();
		if (bspProj == null) {
			UIUtils.showMessageDialog("Change Referenced BSP", "The originally used BSP cannot be found, Please manually set the BSP in the properties.", MessageDialog.ERROR);
			return null;
		}
		
		ChangeReferenceBspDialog dialog = new ChangeReferenceBspDialog(UIUtils.getActiveShell(), appProj);
		int ret = dialog.open();
		if (ret == ChangeReferenceBspDialog.OK) {
			logger.info("Change Referenced BSP starting...");
			updateBsp(appProj, dialog.getNewBsp());
			UIUtils.showMessageDialog("Change Referenced BSP", "Change Referenced BSP Success!", MessageDialog.OK);
			logger.info("Change Referenced BSP done!");
		}
		
		return null;
	}
	
	public void updateBsp(IApplicationProject appProj, IPlatformProject newBspProj) {
		IPlatformProject oldBspProj = appProj.getBspProj();
		
		appProj.setBspProj(newBspProj);
		appProj.saveMetaData();
		
		updateProjectReferences(appProj.getIProject(), oldBspProj.getIProject(), newBspProj.getIProject());
		
		Map<String, String> vars = new HashMap<String, String> ();
		vars.put("bsp_loc", String.format("${workspace_loc:%s}", newBspProj.getName()));
		ProjectUtils.setBuildVariables(appProj.getIProject(), vars);
	}

	public void updateProjectReferences(IProject project, IProject oldBsp, IProject newBsp) {
		try {
			IProjectDescription descripton = project.getDescription();
			java.util.List<IProject> referencedProjects = new ArrayList<>();
			IProject[] refProjects = descripton.getReferencedProjects();
			referencedProjects.add(newBsp);
			for (IProject proj : refProjects) {
				if (!proj.getName().equals(oldBsp.getName())) {
					referencedProjects.add(proj);
				}
			}
			descripton.setReferencedProjects(referencedProjects.<IProject>toArray(new IProject[0]));
			if (project.exists() && project.isAccessible())
				project.setDescription(descripton, null); 
		} catch (CoreException e) {
			logger.error("Failed to update project references {}", e.getMessage());
		}
	}
}
